package com.katze.boot.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.katze.boot.system.dao.UserRoleMapper;
import com.katze.boot.system.domain.User;
import com.katze.boot.system.domain.UserRole;
import com.katze.boot.system.service.UserRoleService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service("userRoleService")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class UserRoleServiceImpl extends ServiceImpl<UserRoleMapper, UserRole> implements UserRoleService {

	@Override
	public void save(User user) {
		if (!user.getRoles().isEmpty()) {
			List<UserRole> list = user.getRoles().stream().map(item -> new UserRole(user.getUserId(), item.getRoleId())).collect(Collectors.toList());
			super.saveBatch(list);
		}
	}

	@Override
	@Transactional
	public Function<Function<String, User>, String> resetUserRoles(User user) {
		return (fun) -> {
			User temp = fun.apply(user.getUsername());
			boolean isClear = false;
			if (user.getRoles().size() == temp.getRoles().size()) {
				if (!user.getRoles().isEmpty()) {
					String r1 = user.getRoles().stream().sorted((o1, o2) -> Math.toIntExact((o1.getRoleId() - o2.getRoleId()))).map(item -> item.getRoleId() + "=" + item.getRoleName()).collect(Collectors.joining(";"));
					String r2 = temp.getRoles().stream().sorted((o1, o2) -> Math.toIntExact((o1.getRoleId() - o2.getRoleId()))).map(item -> item.getRoleId() + "=" + item.getRoleName()).collect(Collectors.joining(";"));
					isClear = !r1.equals(r2);
				}
			} else {
				isClear = true;
			}
			if (isClear) {
				this.baseMapper.delete(new LambdaQueryWrapper<UserRole>().eq(UserRole::getUserId, user.getUserId()));
				List<UserRole> list = user.getRoles().stream().map(role -> new UserRole(user.getUserId(), role.getRoleId())).collect(Collectors.toList());
				this.baseMapper.insert(list);
				return user.getUsername();
			} else {
				return null;
			}
		};
	}

	@Override
	@Transactional
	public void deleteUserRolesByRoleId(Object[] roleIds) {
		this.baseMapper.delete(new LambdaQueryWrapper<UserRole>().in(UserRole::getUserId, roleIds));
	}

	@Override
	public List<String> findUsernameByRoleId(Object[] roleIds) {
		return this.baseMapper.findUsernameByRoleId(roleIds);
	}

}
